# -*- coding: utf-8 -*-
"""
数据格式化器模块

提供各种数据格式化功能，包括：
- 日期时间格式化
- 数字格式化
- 字符串格式化
- 中国特色数据格式化
- 业务数据格式化
- 导出格式化
"""

import re
from datetime import datetime, date
from typing import Any, Optional, List, Dict, Union
from decimal import Decimal
import json

from ..config.settings import get_settings


class DateTimeFormatter:
    """日期时间格式化器"""
    
    def __init__(self):
        self.settings = get_settings()
    
    def format_date(self, date_obj: Union[datetime, date, str], format_str: str = None) -> str:
        """格式化日期"""
        if date_obj is None:
            return ""
        
        if format_str is None:
            format_str = self.settings.date_format
        
        if isinstance(date_obj, str):
            try:
                date_obj = datetime.strptime(date_obj, "%Y-%m-%d")
            except ValueError:
                try:
                    date_obj = datetime.strptime(date_obj, "%Y-%m-%d %H:%M:%S")
                except ValueError:
                    return date_obj
        
        if isinstance(date_obj, datetime):
            return date_obj.strftime(format_str)
        elif isinstance(date_obj, date):
            return date_obj.strftime(format_str)
        
        return str(date_obj)
    
    def format_datetime(self, datetime_obj: Union[datetime, str], format_str: str = None) -> str:
        """格式化日期时间"""
        if datetime_obj is None:
            return ""
        
        if format_str is None:
            format_str = self.settings.datetime_format
        
        if isinstance(datetime_obj, str):
            try:
                datetime_obj = datetime.strptime(datetime_obj, "%Y-%m-%d %H:%M:%S")
            except ValueError:
                try:
                    datetime_obj = datetime.strptime(datetime_obj, "%Y-%m-%d")
                except ValueError:
                    return datetime_obj
        
        if isinstance(datetime_obj, datetime):
            return datetime_obj.strftime(format_str)
        
        return str(datetime_obj)
    
    def format_time(self, time_obj: Union[datetime, str], format_str: str = "%H:%M:%S") -> str:
        """格式化时间"""
        if time_obj is None:
            return ""
        
        if isinstance(time_obj, str):
            try:
                time_obj = datetime.strptime(time_obj, "%H:%M:%S")
            except ValueError:
                try:
                    time_obj = datetime.strptime(time_obj, "%Y-%m-%d %H:%M:%S")
                except ValueError:
                    return time_obj
        
        if isinstance(time_obj, datetime):
            return time_obj.strftime(format_str)
        
        return str(time_obj)
    
    def format_relative_time(self, datetime_obj: Union[datetime, str]) -> str:
        """格式化相对时间"""
        if datetime_obj is None:
            return ""
        
        if isinstance(datetime_obj, str):
            try:
                datetime_obj = datetime.strptime(datetime_obj, "%Y-%m-%d %H:%M:%S")
            except ValueError:
                return datetime_obj
        
        if not isinstance(datetime_obj, datetime):
            return str(datetime_obj)
        
        now = datetime.now()
        diff = now - datetime_obj
        
        if diff.days > 0:
            if diff.days == 1:
                return "1天前"
            elif diff.days < 7:
                return f"{diff.days}天前"
            elif diff.days < 30:
                weeks = diff.days // 7
                return f"{weeks}周前"
            elif diff.days < 365:
                months = diff.days // 30
                return f"{months}个月前"
            else:
                years = diff.days // 365
                return f"{years}年前"
        
        seconds = diff.seconds
        if seconds < 60:
            return "刚刚"
        elif seconds < 3600:
            minutes = seconds // 60
            return f"{minutes}分钟前"
        else:
            hours = seconds // 3600
            return f"{hours}小时前"
    
    def format_duration(self, seconds: int) -> str:
        """格式化持续时间"""
        if seconds is None:
            return ""
        
        if seconds < 0:
            return "0秒"
        
        days = seconds // 86400
        hours = (seconds % 86400) // 3600
        minutes = (seconds % 3600) // 60
        secs = seconds % 60
        
        result = []
        if days > 0:
            result.append(f"{days}天")
        if hours > 0:
            result.append(f"{hours}小时")
        if minutes > 0:
            result.append(f"{minutes}分钟")
        if secs > 0 or not result:
            result.append(f"{secs}秒")
        
        return "".join(result)
    
    def format_age(self, birth_date: Union[datetime, date, str]) -> str:
        """格式化年龄"""
        if birth_date is None:
            return ""
        
        if isinstance(birth_date, str):
            try:
                birth_date = datetime.strptime(birth_date, "%Y-%m-%d").date()
            except ValueError:
                return birth_date
        elif isinstance(birth_date, datetime):
            birth_date = birth_date.date()
        
        if not isinstance(birth_date, date):
            return str(birth_date)
        
        today = date.today()
        age = today.year - birth_date.year - ((today.month, today.day) < (birth_date.month, birth_date.day))
        
        return f"{age}岁"


class NumberFormatter:
    """数字格式化器"""
    
    @staticmethod
    def format_currency(amount: Union[int, float, Decimal], currency: str = "¥") -> str:
        """格式化货币"""
        if amount is None:
            return ""
        
        try:
            amount = float(amount)
            if amount == 0:
                return f"{currency}0.00"
            
            # 添加千分位分隔符
            formatted = f"{amount:,.2f}"
            return f"{currency}{formatted}"
        except (TypeError, ValueError):
            return str(amount)
    
    @staticmethod
    def format_percentage(value: Union[int, float, Decimal], decimal_places: int = 2) -> str:
        """格式化百分比"""
        if value is None:
            return ""
        
        try:
            value = float(value)
            formatted = f"{value:.{decimal_places}f}"
            return f"{formatted}%"
        except (TypeError, ValueError):
            return str(value)
    
    @staticmethod
    def format_number(value: Union[int, float, Decimal], decimal_places: int = 2) -> str:
        """格式化数字"""
        if value is None:
            return ""
        
        try:
            value = float(value)
            if decimal_places == 0:
                return f"{value:,.0f}"
            else:
                return f"{value:,.{decimal_places}f}"
        except (TypeError, ValueError):
            return str(value)
    
    @staticmethod
    def format_file_size(size_bytes: int) -> str:
        """格式化文件大小"""
        if size_bytes is None or size_bytes < 0:
            return ""
        
        if size_bytes == 0:
            return "0 B"
        
        units = ["B", "KB", "MB", "GB", "TB"]
        unit_index = 0
        size = float(size_bytes)
        
        while size >= 1024 and unit_index < len(units) - 1:
            size /= 1024
            unit_index += 1
        
        if unit_index == 0:
            return f"{int(size)} {units[unit_index]}"
        else:
            return f"{size:.2f} {units[unit_index]}"
    
    @staticmethod
    def format_score(score: Union[int, float], max_score: int = 5) -> str:
        """格式化评分"""
        if score is None:
            return ""
        
        try:
            score = float(score)
            if score < 0:
                score = 0
            elif score > max_score:
                score = max_score
            
            # 生成星级显示
            full_stars = int(score)
            half_star = 1 if (score - full_stars) >= 0.5 else 0
            empty_stars = max_score - full_stars - half_star
            
            result = "★" * full_stars
            if half_star:
                result += "☆"
            result += "☆" * empty_stars
            
            return f"{result} ({score:.1f}/{max_score})"
        except (TypeError, ValueError):
            return str(score)


class StringFormatter:
    """字符串格式化器"""
    
    @staticmethod
    def format_phone(phone: str) -> str:
        """格式化手机号"""
        if not phone:
            return ""
        
        # 移除所有非数字字符
        phone = re.sub(r'\D', '', phone)
        
        # 中国大陆手机号格式化
        if len(phone) == 11 and phone.startswith('1'):
            return f"{phone[:3]}-{phone[3:7]}-{phone[7:]}"
        
        # 固定电话格式化
        if len(phone) >= 10:
            if phone.startswith('0'):
                if len(phone) == 11:  # 0XXX-XXXXXXX
                    return f"{phone[:4]}-{phone[4:]}"
                elif len(phone) == 12:  # 0XXX-XXXXXXXX
                    return f"{phone[:4]}-{phone[4:]}"
                elif len(phone) == 10:  # 0XX-XXXXXXXX
                    return f"{phone[:3]}-{phone[3:]}"
        
        return phone
    
    @staticmethod
    def format_id_card(id_card: str) -> str:
        """格式化身份证号"""
        if not id_card:
            return ""
        
        # 移除空格
        id_card = id_card.replace(' ', '')
        
        # 18位身份证格式化
        if len(id_card) == 18:
            return f"{id_card[:6]} {id_card[6:10]} {id_card[10:14]} {id_card[14:]}"
        
        return id_card
    
    @staticmethod
    def format_address(address: str, max_length: int = 50) -> str:
        """格式化地址"""
        if not address:
            return ""
        
        # 移除多余空格
        address = ' '.join(address.split())
        
        # 截断过长地址
        if len(address) > max_length:
            return address[:max_length-3] + "..."
        
        return address
    
    @staticmethod
    def format_name(name: str) -> str:
        """格式化姓名"""
        if not name:
            return ""
        
        # 移除多余空格
        name = ' '.join(name.split())
        
        # 首字母大写（英文名）
        if re.match(r'^[a-zA-Z\s]+$', name):
            return name.title()
        
        return name
    
    @staticmethod
    def format_email(email: str) -> str:
        """格式化邮箱"""
        if not email:
            return ""
        
        return email.lower().strip()
    
    @staticmethod
    def truncate_text(text: str, max_length: int = 100, suffix: str = "...") -> str:
        """截断文本"""
        if not text:
            return ""
        
        if len(text) <= max_length:
            return text
        
        return text[:max_length-len(suffix)] + suffix
    
    @staticmethod
    def format_list(items: List[str], separator: str = "、", max_items: int = 5) -> str:
        """格式化列表"""
        if not items:
            return ""
        
        # 过滤空值
        items = [item for item in items if item]
        
        if len(items) <= max_items:
            return separator.join(items)
        else:
            return separator.join(items[:max_items]) + f"等{len(items)}项"


class ChineseFormatter:
    """中文格式化器"""
    
    @staticmethod
    def format_gender(gender: str) -> str:
        """格式化性别"""
        if not gender:
            return ""
        
        gender = gender.lower()
        gender_map = {
            'male': '男',
            'female': '女',
            'm': '男',
            'f': '女',
            '1': '男',
            '0': '女',
            'man': '男',
            'woman': '女'
        }
        
        return gender_map.get(gender, gender)
    
    @staticmethod
    def format_marital_status(status: str) -> str:
        """格式化婚姻状况"""
        if not status:
            return ""
        
        status_map = {
            'single': '未婚',
            'married': '已婚',
            'divorced': '离异',
            'widowed': '丧偶',
            'separated': '分居'
        }
        
        return status_map.get(status.lower(), status)
    
    @staticmethod
    def format_education(education: str) -> str:
        """格式化教育程度"""
        if not education:
            return ""
        
        education_map = {
            'primary': '小学',
            'middle': '初中',
            'high': '高中',
            'college': '大专',
            'bachelor': '本科',
            'master': '硕士',
            'doctor': '博士'
        }
        
        return education_map.get(education.lower(), education)
    
    @staticmethod
    def format_health_status(status: str) -> str:
        """格式化健康状况"""
        if not status:
            return ""
        
        status_map = {
            'excellent': '健康良好',
            'good': '健康一般',
            'fair': '健康较差',
            'poor': '健康很差'
        }
        
        return status_map.get(status.lower(), status)


class BusinessFormatter:
    """业务数据格式化器"""
    
    @staticmethod
    def format_customer_code(code: str) -> str:
        """格式化客户编号"""
        if not code:
            return ""
        
        # 标准格式：CRM-YYYYMMDD-XXXX
        if len(code) >= 16 and '-' in code:
            return code
        
        # 如果是纯数字，尝试格式化
        if code.isdigit() and len(code) >= 8:
            return f"CRM-{code[:8]}-{code[8:]}"
        
        return code
    
    @staticmethod
    def format_product_code(code: str) -> str:
        """格式化产品编号"""
        if not code:
            return ""
        
        # 标准格式：PRD-XXXX
        if code.startswith('PRD-'):
            return code
        
        return f"PRD-{code}"
    
    @staticmethod
    def format_opportunity_status(status: str) -> str:
        """格式化销售机会状态"""
        if not status:
            return ""
        
        status_map = {
            'lead': '线索',
            'qualified': '合格机会',
            'proposal': '方案阶段',
            'negotiation': '谈判阶段',
            'closed_won': '成交',
            'closed_lost': '失败'
        }
        
        return status_map.get(status.lower(), status)
    
    @staticmethod
    def format_customer_status(status: str) -> str:
        """格式化客户状态"""
        if not status:
            return ""
        
        status_map = {
            'active': '有效客户',
            'potential': '潜在客户',
            'inactive': '无效客户',
            'converted': '已成交客户',
            'blacklist': '黑名单'
        }
        
        return status_map.get(status.lower(), status)
    
    @staticmethod
    def format_tour_status(status: str) -> str:
        """格式化出团状态"""
        if not status:
            return ""
        
        status_map = {
            'planning': '筹备中',
            'recruiting': '招募中',
            'confirmed': '已确认',
            'ongoing': '进行中',
            'completed': '已完成',
            'cancelled': '已取消'
        }
        
        return status_map.get(status.lower(), status)
    
    @staticmethod
    def format_activity_type(activity_type: str) -> str:
        """格式化活动类型"""
        if not activity_type:
            return ""
        
        type_map = {
            'product_intro': '产品推介会',
            'destination_share': '目的地分享会',
            'customer_thanks': '客户答谢会',
            'tea_party': '小型茶话会',
            'one_on_one': '一对一咨询',
            'phone_invite': '电话邀约',
            'wechat_group': '微信群活动',
            'video_share': '视频分享会',
            'live_stream': '直播介绍',
            'home_visit': '上门拜访'
        }
        
        return type_map.get(activity_type.lower(), activity_type)


class ExportFormatter:
    """导出格式化器"""
    
    @staticmethod
    def format_for_excel(data: List[Dict[str, Any]], headers: Dict[str, str] = None) -> List[List[str]]:
        """格式化Excel导出数据"""
        if not data:
            return []
        
        # 获取所有字段
        all_fields = set()
        for item in data:
            all_fields.update(item.keys())
        
        # 排序字段
        sorted_fields = sorted(all_fields)
        
        # 创建标题行
        if headers:
            title_row = [headers.get(field, field) for field in sorted_fields]
        else:
            title_row = sorted_fields
        
        # 创建数据行
        result = [title_row]
        for item in data:
            row = []
            for field in sorted_fields:
                value = item.get(field, "")
                # 格式化值
                if isinstance(value, datetime):
                    value = value.strftime("%Y-%m-%d %H:%M:%S")
                elif isinstance(value, date):
                    value = value.strftime("%Y-%m-%d")
                elif isinstance(value, (int, float, Decimal)):
                    value = str(value)
                elif value is None:
                    value = ""
                else:
                    value = str(value)
                row.append(value)
            result.append(row)
        
        return result
    
    @staticmethod
    def format_for_csv(data: List[Dict[str, Any]], headers: Dict[str, str] = None) -> str:
        """格式化CSV导出数据"""
        import csv
        import io
        
        if not data:
            return ""
        
        # 获取所有字段
        all_fields = set()
        for item in data:
            all_fields.update(item.keys())
        
        sorted_fields = sorted(all_fields)
        
        # 创建CSV内容
        output = io.StringIO()
        writer = csv.writer(output)
        
        # 写入标题行
        if headers:
            title_row = [headers.get(field, field) for field in sorted_fields]
        else:
            title_row = sorted_fields
        writer.writerow(title_row)
        
        # 写入数据行
        for item in data:
            row = []
            for field in sorted_fields:
                value = item.get(field, "")
                # 格式化值
                if isinstance(value, datetime):
                    value = value.strftime("%Y-%m-%d %H:%M:%S")
                elif isinstance(value, date):
                    value = value.strftime("%Y-%m-%d")
                elif value is None:
                    value = ""
                else:
                    value = str(value)
                row.append(value)
            writer.writerow(row)
        
        return output.getvalue()
    
    @staticmethod
    def format_for_json(data: List[Dict[str, Any]], pretty: bool = True) -> str:
        """格式化JSON导出数据"""
        if not data:
            return "[]"
        
        # 转换数据
        formatted_data = []
        for item in data:
            formatted_item = {}
            for key, value in item.items():
                if isinstance(value, datetime):
                    formatted_item[key] = value.strftime("%Y-%m-%d %H:%M:%S")
                elif isinstance(value, date):
                    formatted_item[key] = value.strftime("%Y-%m-%d")
                elif isinstance(value, Decimal):
                    formatted_item[key] = float(value)
                else:
                    formatted_item[key] = value
            formatted_data.append(formatted_item)
        
        if pretty:
            return json.dumps(formatted_data, ensure_ascii=False, indent=2)
        else:
            return json.dumps(formatted_data, ensure_ascii=False)


# 全局格式化器实例
datetime_formatter = DateTimeFormatter()
number_formatter = NumberFormatter()
string_formatter = StringFormatter()
chinese_formatter = ChineseFormatter()
business_formatter = BusinessFormatter()
export_formatter = ExportFormatter()


# 便捷函数
def format_date(date_obj: Union[datetime, date, str], format_str: str = None) -> str:
    """格式化日期"""
    return datetime_formatter.format_date(date_obj, format_str)


def format_datetime(datetime_obj: Union[datetime, str], format_str: str = None) -> str:
    """格式化日期时间"""
    return datetime_formatter.format_datetime(datetime_obj, format_str)


def format_currency(amount: Union[int, float, Decimal], currency: str = "¥") -> str:
    """格式化货币"""
    return number_formatter.format_currency(amount, currency)


def format_phone(phone: str) -> str:
    """格式化手机号"""
    return string_formatter.format_phone(phone)


def format_percentage(value: Union[int, float, Decimal], decimal_places: int = 2) -> str:
    """格式化百分比"""
    return number_formatter.format_percentage(value, decimal_places)


def format_relative_time(datetime_obj: Union[datetime, str]) -> str:
    """格式化相对时间"""
    return datetime_formatter.format_relative_time(datetime_obj)


def format_customer_status(status: str) -> str:
    """格式化客户状态"""
    return business_formatter.format_customer_status(status)


def format_file_size(size_bytes: int) -> str:
    """格式化文件大小"""
    return number_formatter.format_file_size(size_bytes)


def truncate_text(text: str, max_length: int = 100, suffix: str = "...") -> str:
    """截断文本"""
    return string_formatter.truncate_text(text, max_length, suffix)